﻿using System;
using Tao.OpenGl;
using Aeon.Framework.Objects;

namespace Aeon.Framework
{

/// <summary>
/// Wrapper container and controller for an AeonLight.
/// 
/// </summary>
internal sealed class AeonLightbulb : IKey, IMove, ITurn
    {
    // --- Attributes:
    
    private static UInt16 lightsMax = 8;        // Number of OpenGL max lights.
    private static UInt16 lights = lightsMax;   // Available lights counter.
    
    private Boolean valid;                      // Object state flag.
    
    private UInt16 num;                         // OpenGl constant reference.
    private String key;                         // Light identifier.
    private Boolean off;                        // Disabled light.
    private AeonLight light;                    // Light object.
    
    // --- Properties:
    
    public String ID { get { return(key); } }
    public Position Origin { get { return(light.Origin); } }
    public Orientation Angle { get { return(light.Angle); } }
    
    // --- Constructor:

    internal AeonLightbulb(AeonLight light)
        {
        if (lights > 0)
           {
           num = --lights;
        
           this.light = light;
           this.key = light.ID;
        
           off = true;
           valid = true;
           }
           
        else valid = false;
        }
        
    // --- Public Methods:
    
    public void MoveTo(Position pos)
        {
        if (valid)
            {            
            light.MoveTo(pos);
            
            if (!off)
               {
               off = true;
               lightSwitch();
               
               off = false;
               lightSwitch();
               }
            }
        }
        
    public void MoveBy(IVector vec)
        {
        if (valid)
            {            
            light.MoveBy(vec);
            
            if (!off)
               {
               off = true;
               lightSwitch();
               
               off = false;
               lightSwitch();
               }
            }
        }

    public void RotateTo(Orientation ang)
        {
        if (valid)
            {            
            light.RotateTo(ang);
            
            if (!off)
               {
               off = true;
               lightSwitch();
               
               off = false;
               lightSwitch();
               }
            }
        }
        
    public void RotateBy(Orientation ang)
        {
        if (valid)
            {            
            light.RotateBy(ang);
            
            if (!off)
               {
               off = true;
               lightSwitch();
               
               off = false;
               lightSwitch();
               }
            }
        }

    /// <summary>
    /// Activates an OpenGL native light.
    /// Requirea an active OpenGL context. [TODO] Really? That's bad.
    /// 
    /// </summary>
    internal bool TurnOn()
        {
        if (off && valid)
           {
           off = false;        
           lightSwitch();
           
           return(true);
           }
           
        return(false);
        }

    /// <summary>
    /// Deactivates an OpenGL native light.
    /// Requires an active OpenGL context. [TODO] Really? That's bad.
    /// 
    /// </summary>
    internal bool TurnOff()
        {
        if (!off && valid)
           {
           lights++;
           off = true;
           valid = false;
           
           lightSwitch();
           return(true);
           }
           
        return(false);
        }
        
    // --- Private Methods:

    private void lightSwitch()
        {
        Int32 counter = lightsMax - lights;     // This is the number of active lights.
        Int32 reference = Gl.GL_LIGHT0 + num;   // This is a miniature 0-7 'switch' statement. 
        
        if (off) 
           {
           if (counter == 0)
              {
              // Disable all lights:
              Gl.glDisable(Gl.GL_LIGHTING);
              Gl.glEnable(Gl.GL_NORMALIZE);
              //Gl.glDisable(Gl.GL_RESCALE_NORMAL);
              }

           // Disable this light:
           Gl.glDisable(reference);
           }

        else {
             if (counter == 1)
                {
                // Enable all lights:
                Gl.glEnable(Gl.GL_LIGHTING);
                Gl.glEnable(Gl.GL_NORMALIZE);
                //Gl.glEnable(Gl.GL_RESCALE_NORMAL);
                }
            
             // Enable this light:
             Gl.glLightfv(reference, Gl.GL_AMBIENT, light.VectorAmbient); 
             Gl.glLightfv(reference, Gl.GL_DIFFUSE, light.VectorDiffuse);
             Gl.glLightfv(reference, Gl.GL_SPECULAR, light.VectorSpecular);
             Gl.glLightfv(reference, Gl.GL_POSITION, light.VectorPosition);
 
             Gl.glEnable(reference);             
             }
        }
        
    }


}
    